/**
 * @file serial_driver.h
 * @author circleup (circleup@foxmail.com)
 * @brief 串口数据处理
 * @version 0.1
 * @date 2020-07-13
 * 
 * @copyright Copyright (c) 2020
 * 
 */

#ifndef _SERIAL_DRIVER_H_
#define _SERIAL_DRIVER_H_

#include "ros/ros.h"
#include "storm_car/car_status.h"
#include <serial/serial.h>

/**
 * @brief 串口缓存数组大小
 * 
 */
#define BUFFERSIZE 2048

/**
 * @brief 串口缓存结构体定义
 * 
 */

typedef struct{
  uint16_t WRHead;  ///< 写标记
  uint16_t RDTail;  ///< 读标记

  char Buffer[BUFFERSIZE];  ///< 缓存数组
} BUFFER_t;

///< 串口缓存结构体
extern BUFFER_t g_serial_buffer;

/**
 * @brief 串口数据分析函数
 * 
 * @param param 串口数据存放数组
 * @return storm_car::car_status serial_receive_data 话题发布消息
 */
storm_car::car_status AnalysisData(char * param);

/**
 * @brief 字符串分割函数
 * 
 * @param s 待分割的字符串
 * @param v 存放分割后的字符子串
 * @param c 分割标志
 */
void SplitString(const std::string& s, std::vector<std::string>& v, const std::string& c);

/**
 * @brief 字符串转双精度浮点型函数
 * 
 * @param param 待转换字符串
 * @return double 转换后的浮点数
 * @details  转换精度：最小有效数字可达15位
 */
double StringToDouble(std::string param);

/**
 * @brief 双精度浮点数转字符串
 * 
 * @param param 待转换浮点数
 * @param length 最小有效数字位数
 * @return std::string 转换后的字符串
 * @details  转换精度：最小有效数字：length位；在整数为0时，可保证小数的有效数字位数为length位
 * @bug 负数转换有问题
 */
std::string DoubleToString(double param, uint8_t length);

/**
 * @brief 串口缓存结构体初始化
 * 
 */
void BufferInit(void);

/**
 * @brief 串口缓存结构体数组打印（16 进制）
 * 
 */
void BufferPrintf(void);

/**
 * @brief 数组打印（16 进制）
 * 
 * @param src 
 * @param len 
 */
void ArrayPrintf(char * src, uint16_t len);

/**
 * @brief 串口缓存写函数
 * 
 * @param dest 串口缓存结构体
 * @param src 写入的字符串
 * @param len 写入的字符串长度
 * @return uint8_t 写入的数据长度
 */
uint8_t WriteToBuffer(BUFFER_t * dest, char * src, uint16_t len);

/**
 * @brief 串口缓存读函数
 * 
 * @param dest 存放读出数据的数组
 * @param src 串口缓存结构体
 * @param len 存放读出数据的数组长度
 * @return uint8_t 读出的数据长度
 */
uint8_t ReadFromBuffer(char * dest, BUFFER_t * src, uint16_t len);

/**
 * @brief 写数据到文件
 * 
 * @param param 要写入的字符串
 * @return true 写入成功
 * @return false 写入失败
 */
bool WriteToFile(char * param);

/**
 * @brief 保存 GPS 航向角，经纬度，速度到文件
 * 
 * @param param 要写入的 GPS 数据 
 * @return true 写入成功
 * @return false 写入失败
 */
bool WriteToFile(storm_car::car_status param);

/**
 * @brief 
 * 
 * @return std::string 
 */
std::string ReadFromFile();

/**
 * @brief 初始化 RVIZ 显示点
 * 
 */
void init_rviz_points_listener();

/**
 * @brief 更新 RVIZ 轨迹（相对于当前点）
 * 
 * @param longitude 当前点经度
 * @param lattitude 当前点纬度
 */
void update_rviz_points_listener(double longitude, double lattitude);

#endif